<?php

/**
 * MySQL class to handle all DB needs. We use mysqli as mysql is no longer updated 
 * in PHP.
 * 
 * NOTE: We need to come up with a good way to intercept ALL errors and use our 
 * own handlers. This way we stop using 'exit' and can customize the error ouput
 * format so that it is more compatible with any UI implemented.
 * 
 * @todo Actually do some sort Error handling and custom output
 */

namespace Kesillo\Db;

class MySql
{
    
    private $server = null;
    private $username = null;
    private $password = null;
    private $link = null;
    private $database = null;

    /**
     * __construct(): simple and basic constructor. We might add more code to it
     * but for now, this is all it's gonna do.
     * 
     * @param array $config Assosiative array with the classe's properties and values
     */
    public function __construct($config)
    {
        foreach ($config as $property => $value) {
            $this->$property = $value;
        }
        
        $this->Connect();
    }
    
    /**
     * __set(): use setters so that we can do some checking with the vars later on 
     * for the moment we will just set them up. 
     * 
     * @param string $property The name of the property
     * @param string $value The value of the property
     */
    public function __set($property, $value)
    {
        $this->$property = $value;
    }    
    
    /**
     * __get(): just a getter. 
     * 
     * @param string $property The name of the property to return
     */
    public function __get($property)
    {
        return $this->$property;
    }

    /**
     * Connect(). Attempts to connect to the MySQL server 
     * 
     * @return MySQL Link id or false
     */
    private function Connect()
    {
        try {
            $this->link = @mysqli_connect($this->server, $this->username, $this->password);
        }
        catch ( Exception $e )
        {
            throw new Exception('errors get crazy');
        }
        
        
        if (!$this->link)
            exit ('Unable to Connect to MySQL Server. Error#:'. mysqli_connect_errno() . ' - ' . mysqli_connect_error());
        
        return;
            
    }
    
    /**
     * Fetches records from the database 
     */
    public function SelectRecords()
    {
        
    }
    
    /**
     * We prepare and execute an INSERT into a given table. We expect the #recordSet
     * to be a an array in the form of:
     * Array(
     *      'fields' => Array( 'FIELD1', 'FIELD2', 'FIELD3' ),
     *      'values' => Array(
     *          Array( 'value1', 'value2', 'value3' ),
     *          Array( 'value4', 'value5', 'value6' )
     *      )
     *  )
     * 
     * NOTE: We might need some extra work here, we might also need to split 
     * this into other methods, but for the moment this works.
     * 
     * @param string $table
     * @param array $recordSet
     * @return resource 
     */
    public function InsertRecordSet($table = null, $recordSet = Array())
    {
        if ($table == null || count($recordSet) === 0)
            exit ('You must provide a table name. Check params');
        
        $values = null;
        $fields = null;
        
        // Let's build $flieds and $values part of the SQL string
        $fields = ' ('.implode(', ', $recordSet['fields']).')';
        $values = ' VALUES ';
        
        foreach ($recordSet['values'] as $row) {
            $values .= ', ('.implode(', ', $row). ')';
        }
        
        // Because above we add comas, we need to remove the first occurance
        // of a comas so we can have a valid SQL statement. We escape it here too.
        $values = mysqli_real_escape_string($this->link, substr_replace($values, '', strpos( $values, ','), 1));
        
        return @mysqli_query($this->link, 'INSERT INTO '.$table.$fields.$values);
    }
    
    /**
     * Updates a single record in a given table. 
     * 
     * - First param takes the Table as a string
     * - The second paramr takes an Array containing 1 or more field to update
     * - The third param is an assosiative array to match the record. EX: array( 'ID' => 'Value') = WHERE ID = Value
     * 
     * @param string $table
     * @param array $fields
     * @param array $condition
     * @return resource 
     */
    public function UpdateRecord($table = null, $fields = Array(), $condition = Array())
    {
        if ($table == null || count($fields) === 0 || count($condition) > 1)
            exit ('You must provide a table name. Check params');
        
        $setFieldsValues = ' SET ';
        
        foreach ($fields as $field => $value) {
            $setFieldsValues .= $field.' = '.$value.', ';
        }

        // Escape string and remove the last char in the string, which is always a ','
        $setFieldsValues = mysqli_real_escape_string($this->link, substr_replace($setFieldsValues, '', strrpos( $setFieldsValues, ','), 1));
        
        return @mysqli_query($this->link, 'UPDATE '.$table.$setFieldsValues.' WHERE '.key($condition).' = '.$condition[key($condition)]);   
    }
    
    /**
     * Deletes a single record where all the conditions are met
     * 
     * - $table: the table to delete from
     * - $condition[]: assosiative array with count of at least 1. EX: array( 'ID' => 'Value') = WHERE ID = Value
     * - returns the myqli resource.
     * 
     * LIMIT 1 is for safety. Just repeat the method call in a for loop or similar.
     * 
     * @param string $table
     * @param array $condition
     * @return resource 
     */
    public function DeleteRecord($table = null, $condition = Array())
    {
        if ($table === null || count($condition) === 0)
            exit ('You must provide a table name. Check params');
        
        $fieldsValues = null;
        
        foreach ($condition as $field => $value) {
            $fieldsValues .= $field.' = '.$value. ' AND ';
        }
        
        $fieldsValues = substr_replace($fieldsValues, '', strrpos($fieldsValues, 'AND'), 3);
        $fieldsValues = mysqli_real_escape_string($this->link, $fieldsValues);
        
        return @mysqli_query($this->link, 'DELETE FROM '.$table.' WHERE '.$fieldsValues.' LIMIT 1');
    }
    
    /**
     * Executes a SQL file. The function will only look in
     * the App's Resources folder. There are no security checks so make sure you 
     * really intend to do it.
     * 
     * This method should only be used when creating the initial DC schema.
     * 
     * Once the file is used/executed it will be renamed. The new name will have 
     * the date and time as its extension.
     * 
     * - $app: the app name.
     * - $sqlFile: the sql file to execute: this should be: exec<App>.sql
     *  
     * @param string $app
     * @return bool
     */
    public function ExecuteSqlFile($app)
    {
        if ( $app === null || $app == '')
            exit ('Check Params passed to InitDatabase');
        
        $sqlFile = file_get_contents(APPSPATH.'exec'.$app.'.sql');
        if (!$sqlFile)
            exit ('Unable to read SQL file');
        
        return @mysqli_multi_query($this->link, $sqlFile);
    }
}
